#include "deploy/m_data_center_deploy.h"
#include "m_data_center.h"
#include "m_list.h"
#include "m_memory.h"
#include "m_mutex.h"


#ifdef __cplusplus
extern "C" {
#endif


/**
 * 数据中心节点结构体
 */
typedef struct MDataCenterNodeTag
{
    Int8   client_name_[32];  // 客户端名称
    MList  list_;             // 消息列表
} MDataCenterNode;

/**
 * 数据中心管理器结构体
 */
typedef struct MDataCenterManagerTag
{
    MList  client_list_;  // 客户端列表
    MMutex lock_;
} MDataCenterManager;

static Bool               is_init_ = False;
static MDataCenterManager data_center_manager_;


Int32 MDataCenterInit(void)
{
    if (! is_init_)
    {
        memset(&data_center_manager_, 0x00, sizeof(MDataCenterManager));
        MListCreate(&data_center_manager_.client_list_);
        MMutexCreate(&data_center_manager_.lock_);
        is_init_ = True;
    }

    return kErrCodeSucc;
}

Int32 MDataCenterFini(void)
{
    if (is_init_)
    {
        if (MMutexEnter(&data_center_manager_.lock_))
        {
            MDataCenterNode *client = NULL;
            while (client = (MDataCenterNode *)MListPop(&data_center_manager_.client_list_))
            {
                MListDestroy(&client->list_);

                MFree(client);
            }

            MListDestroy(&data_center_manager_.client_list_);
            MMutexLeave(&data_center_manager_.lock_);
            MMutexDestory(&data_center_manager_.lock_);
        }
        memset(&data_center_manager_, 0x00, sizeof(MDataCenterManager));
    }

    return kErrCodeSucc;
}


/**
 * @brief 注册客户端
 *
 * @param client_name 客户端名称
 * @return 客户端句柄，NULL 则注册失败
 */
MDCClientHandle MDataCenterLogin(const Int8 *client_name)
{
    if (client_name == NULL)
    {
        return NULL;
    }

    MDCClientHandle result = NULL;

    if (is_init_)
    {
        MDataCenterNode *new_client = (MDataCenterNode *)MMalloc(sizeof(MDataCenterNode));

        if (new_client != NULL)
        {
            memset(new_client, 0x00, sizeof(MDataCenterNode));
            strncpy(new_client->client_name_, client_name, sizeof(new_client->client_name_));
            new_client->client_name_[sizeof(new_client->client_name_) - 1] = '\0';

            MListCreate(&new_client->list_);

            if (MMutexEnter(&data_center_manager_.lock_))
            {
                if (MListPush(&data_center_manager_.client_list_, new_client) == kErrCodeSucc)
                {
                    result = (MDCClientHandle)new_client;
                }
                else
                {
                    MFree((void *)new_client);
                }

                MMutexLeave(&data_center_manager_.lock_);
            }
            else
            {
                MFree((void *)new_client);
            }
        }
    }

    return result;
}

/**
 * @brief 注销客户端
 *
 * @param client_handle 客户端句柄
 * @return 执行结果，详见 MErrCode
 */
Int32 MDataCenterLogout(MDCClientHandle client_handle)
{
    if (client_handle == NULL)
    {
        return kErrCodeParamsErr;
    }

    Int32 result = kErrCodeElse;

    if (is_init_)
    {
        if (MMutexEnter(&data_center_manager_.lock_))
        {
            MDataCenterNode *client;

            result = kErrCodeItemNotExist;

            MListIteratorReset(&data_center_manager_.client_list_);
            while (client = MListIteratorNext(&data_center_manager_.client_list_))
            {
                if (client == client_handle)
                {
                    if (MListIteratorPop(&data_center_manager_.client_list_) != NULL)
                    {
                        result = kErrCodeSucc;
                    }
                    break;
                }
            }

            MMutexLeave(&data_center_manager_.lock_);
        }
        else
        {
            result = kErrCodeGetLockErr;
        }
    }
    else
    {
        result = kErrCodeNotCreate;
    }

    return result;
}

/**
 * @brief 创建交互消息，内含内存申请
 *
 * @param content_size 附加内存长度
 * @return MDataCenterMsg* 返回的消息，为NULL则内存申请失败
 */
MDataCenterMsg* MDataCenterCreateMsg(UInt16 content_size)
{
    MDataCenterMsg* result = NULL;

    result = (MDataCenterMsg *)MMalloc(sizeof(MDataCenterMsg) + content_size);

    return result;
}

/**
 * @brief 销毁交互消息，内含内存释放
 *
 * @param msg_t 待销毁消息结构体
 */
void MDataCenterDestroyMsg(MDataCenterMsg *msg_t)
{
    if (msg_t != NULL)
    {
        MFree((void *)msg_t);
    }
}

/**
 * @brief 发送交互消息，需先创建
 *
 * @param recviver_name 接收者名称，详见 MDataCenterUser
 * @param msg_t 待发送消息结构体，由 MDataCenterCreateMsg 创建
 * @return 执行结果，详见 MErrCode
 */
Int32 MDataCenterSendMsg(const Int8 *recviver_name, MDataCenterMsg *msg_t)
{
    if (recviver_name == NULL || msg_t == NULL)
    {
        return kErrCodeParamsErr;
    }

    Int32 result = kErrCodeElse;

    if (is_init_)
    {
        if (MMutexEnter(&data_center_manager_.lock_))
        {
            MDataCenterNode *client;

            result = kErrCodeItemNotExist;

            MListIteratorReset(&data_center_manager_.client_list_);
            while (client = MListIteratorNext(&data_center_manager_.client_list_))
            {
                if (strncmp(client->client_name_, recviver_name, sizeof(client->client_name_)) == 0)
                {
                    if (MListPush(&client->list_, msg_t) == kErrCodeSucc)
                    {
                        result = kErrCodeSucc;
                    }
                    break;
                }
            }

            MMutexLeave(&data_center_manager_.lock_);
        }
        else
        {
            result = kErrCodeGetLockErr;
        }
    }
    else
    {
        result = kErrCodeNotCreate;
    }

    return result;
}

/**
 * @brief 获取交互消息，但不取出，禁止调用接口摧毁消息
 *
 * @param client_handle 客户端句柄
 * @return MDataCenterMsg* NULL 表示没有消息，否则返回消息结构体
 */
MDataCenterMsg* MDataCenterPeekMsg(MDCClientHandle client_handle)
{
    if (client_handle == NULL)
    {
        return NULL;
    }

    MDataCenterMsg* result = NULL;

    if (is_init_)
    {
        if (MMutexEnter(&data_center_manager_.lock_))
        {
            result = MListPeek(&((MDataCenterNode*)client_handle)->list_);

            MMutexLeave(&data_center_manager_.lock_);
        }
    }

    return result;
}

/**
 * @brief 获取交互消息，并取出，需调用接口摧毁消息
 *
 * @param client_handle 客户端句柄
 * @return MDataCenterMsg* NULL 表示没有消息，否则返回消息结构体
 */
MDataCenterMsg* MDataCenterPopMsg(MDCClientHandle client_handle)
{
    if (client_handle == NULL)
    {
        return NULL;
    }

    MDataCenterMsg* result = NULL;

    if (is_init_)
    {
        if (MMutexEnter(&data_center_manager_.lock_))
        {
            result = MListPop(&((MDataCenterNode*)client_handle)->list_);

            MMutexLeave(&data_center_manager_.lock_);
        }
    }

    return result;
}

#ifdef __cplusplus
} // extern "C" {
#endif
